﻿using System;
using System.Collections.Specialized;
using System.Net.Http;

namespace RESTfulCore
{
    public static class HttpClientFactory
    {
        private static HttpClient _httpClient;
        private static readonly HybridDictionary HybridDictionary = new HybridDictionary(false);

        private static EndPoint EndPoint<T>()
        {
            var contract = typeof(T);
            var contractName = contract.Name;
            var endPoint = RestClientConfigurationSection.Config().EndPoints[contractName];
            return endPoint;
        }

        private static HttpClient HttpClient(EndPoint endPoint)
        {
            return new HttpClient
            {
                BaseAddress = new Uri(endPoint.Address),
                Timeout = endPoint.Timeout,
                MaxResponseContentBufferSize = endPoint.MaxBufferSize
            };
        }

        /// <summary>
        /// Creates a brand new http client every time. Avoid using this one if possible.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static HttpClient CreateHttpClient<T>()
        {
            var endPoint = EndPoint<T>();

            return HttpClient(endPoint);
        }

        /// <summary>
        /// Creates a single http client that is re-used for all different types of contracts.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static HttpClient CreateSingleHttpClient<T>()
        {
            var endPoint = EndPoint<T>();

            if (_httpClient == null)
                _httpClient = new HttpClient();

            _httpClient.BaseAddress = new Uri(endPoint.Address);
            _httpClient.Timeout = endPoint.Timeout;
            _httpClient.MaxResponseContentBufferSize = endPoint.MaxBufferSize;


            return _httpClient;
        }

        /// <summary>
        /// Creates a new instance of the http client based on the contract, stores it into the connection pool and re-uses it upon request. Use this one if you can.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static HttpClient ReuseHttpClientFromHttpClientConnectionPool<T>()
        {
            var key = typeof(T).FullName;

            if (HybridDictionary.Contains(key) && HybridDictionary[key] != null)
                return HybridDictionary[key] as HttpClient;

            var endPoint = EndPoint<T>();

            var httpClient = HttpClient(endPoint);

            HybridDictionary.Add(key, httpClient);

            return HybridDictionary[key] as HttpClient;
        }
    }
}